#include <iostream>
#include <sstream>
#include "PopupSettings.hpp"
#include "PopupUsersTableModel.hpp"
#include "PopupSetupDialog.hpp"
#include "PopupGuiCore.hpp"
#include "PopupUtilities.hpp"

using namespace std;
using namespace Popup;
using namespace utilities;
using namespace PopupUtils;

typedef enum {
  TABLE_COLUMN_MIN        = 0,
  TABLE_COLUMN_USERID     = TABLE_COLUMN_MIN,
  TABLE_COLUMN_USERNAME   = 1,
  TABLE_COLUMN_USERMODE   = 2,
  TABLE_COLUMN_LIKE       = 3,
  TABLE_COLUMN_DONTLIKE   = 4,
  TABLE_COLUMN_POETRY     = 5,
  TABLE_COLUMN_FUCK       = 6,
  TABLE_COLUMN_MAX        = TABLE_COLUMN_FUCK
} TableColumnIndex;

enum {
  POPUP_IS_RECORD = PopupGuiCore::POPUP_USER_ID + 1
};

struct RateItem2ColumnIndex {
  UserRateItem item;
  TableColumnIndex index;
};

PopupUsersTableModel::PopupUsersTableModel()
  : QStandardItemModel(0,1), m_openBrush(QColor("#67B572")),
    m_promptBrush(QColor("#F2B45C")), m_txtOnlyBrush(QColor("#BE58C7")),
    m_muteBrush(QColor("#E84646")), m_deadBrush(QColor("#A8A8A8"))
{
  setHorizontalHeaderLabels(QStringList() 
                << "UserID"
                << tr("Nickname")
                << tr("Mode"));
  QIcon _iconlike;
  _iconlike.addFile(QString::fromUtf8(":/images/popup_like.png"),
                QSize(24,24), QIcon::Normal, QIcon::Off);
  QStandardItem *_likeHeader = new QStandardItem(_iconlike, "");
  setHorizontalHeaderItem(TABLE_COLUMN_LIKE, _likeHeader);

  QIcon _icondontlike;
  _icondontlike.addFile(QString::fromUtf8(":/images/popup_dislike.png"),
                QSize(24,24), QIcon::Normal, QIcon::Off);
  QStandardItem *_dontlikeHeader = new QStandardItem(_icondontlike, "");
  setHorizontalHeaderItem(TABLE_COLUMN_DONTLIKE, _dontlikeHeader);

  QIcon _iconpoetry;
  _iconpoetry.addFile(QString::fromUtf8(":/images/popup_pointfinesse.png"),
                QSize(24,24), QIcon::Normal, QIcon::Off);
  QStandardItem *_poetryHeader = new QStandardItem(_iconpoetry, "");
  setHorizontalHeaderItem(TABLE_COLUMN_POETRY, _poetryHeader);

  QIcon _iconfuck;
  _iconfuck.addFile(QString::fromUtf8(":/images/popup_fuckyou20x20.png"),
                QSize(24,24), QIcon::Normal, QIcon::Off);
  QStandardItem *_fuckHeader = new QStandardItem(_iconfuck, "");
  setHorizontalHeaderItem(TABLE_COLUMN_FUCK, _fuckHeader);
}

Qt::ItemFlags PopupUsersTableModel::flags(const QModelIndex &) const
{
  return Qt::ItemIsSelectable|Qt::ItemIsEnabled;
}

void PopupUsersTableModel::selectUsers(QItemSelection & p_selection,
                                       const Popup::UserList & p_users)
{
  for (int _row = 0; _row < rowCount(); _row++) {
    QStandardItem *_item = item(_row, 0);
    UserID _currentUserID = _item->data(PopupGuiCore::POPUP_USER_ID).toUInt();
    UserList::const_iterator _it;
    for (_it = p_users.begin(); _it != p_users.end(); _it++) {
      if (*_it == _currentUserID) {
        p_selection.select(index(_row, TABLE_COLUMN_MIN),
                           index(_row, TABLE_COLUMN_MAX));
      }
    }
  }
}

const QBrush & PopupUsersTableModel::selectBrush(const User *p_user)
{
  if (!p_user->isAlive()) {
    return m_deadBrush;
  } else {
    switch (p_user->getMode()) {
      case POPUP_MODE_DEFAULT:
        return m_openBrush;
      case POPUP_MODE_PROMPT:
        return m_promptBrush;
      case POPUP_MODE_TEXTONLY:
        return m_txtOnlyBrush;
      case POPUP_MODE_MUTED:
        return m_muteBrush;
      default:
        return m_openBrush;
    }
  }
}

void PopupUsersTableModel::removeAll()
{
  while (rowCount() > 0) {
    QList<QStandardItem*> _removedItems = takeRow(0);
    for (QList<QStandardItem*>::iterator _itDel = _removedItems.begin();
        _itDel != _removedItems.end(); _itDel++) {
      delete *_itDel;
    }
  }
}

void PopupUsersTableModel::updateUser(const Popup::User *p_user,
                                      unsigned short p_updateMask,
                                      bool p_isNewUser)
{
  // Nothing to do if update concerns myself
  if (p_user->getID() == getMyID())
  {
    return;
  }

  QModelIndex _index;
  int _row = 0;
  bool _found = false;

  // First things first: try to find this user in the list
  for (_row = 0; _row < rowCount(); _row++) {
    QStandardItem *_item = item(_row, 0);
    if (_item->data(PopupGuiCore::POPUP_USER_ID).toUInt() == p_user->getID()) {
      _found = true;
      break;
    }
  }

  // Create user in the list if he's not already in
  if (p_isNewUser && !_found)
  {
    const QBrush & _foreground = selectBrush(p_user);

    insertRows(0, 1, _index);

    // Set ID
    _index = index(0,TABLE_COLUMN_USERID);
    setData(_index, (int) p_user->getID(), PopupGuiCore::POPUP_USER_ID);

    // Set nickname and avatar
    _index = index(0,TABLE_COLUMN_USERNAME);
    QString _nickname = QString::fromUtf8(p_user->getNickname().c_str());
    setData(_index, _foreground, Qt::ForegroundRole);
    setData(_index, _nickname);

    if (QFile::exists(p_user->getAvatar().c_str())) {
      QIcon _icon;
      _icon.addFile(QString::fromUtf8(p_user->getAvatar().c_str()), QSize(24,24));
      QIcon::Mode _mode = (p_user->isAlive()? QIcon::Normal : QIcon::Disabled);
      QPixmap _pixmap = _icon.pixmap(QSize(24,24), _mode);
      _icon.addPixmap(_pixmap);
      setData(_index, _icon, Qt::DecorationRole);
    }

    // Set mode
    _index = index(0,TABLE_COLUMN_USERMODE);
    setData(_index, _foreground, Qt::ForegroundRole);
    setData(_index, modeToString(p_user->getMode()));

    // Init stats
    _index = index(0,TABLE_COLUMN_LIKE);
    setData(_index, _foreground, Qt::ForegroundRole);
    setData(_index, "-");
    _index = index(0,TABLE_COLUMN_DONTLIKE);
    setData(_index, _foreground, Qt::ForegroundRole);
    setData(_index, "-");
    _index = index(0,TABLE_COLUMN_POETRY);
    setData(_index, _foreground, Qt::ForegroundRole);
    setData(_index, "-");
    _index = index(0,TABLE_COLUMN_FUCK);
    setData(_index, _foreground, Qt::ForegroundRole);
    setData(_index, "-");
  }

  // This is now a new user
  else
  {


    // User not found!! Strange!
    if (!_found) {
      trace("Ooops! %s:%d", __FUNCTION__, __LINE__);
    }
    else {

      if (p_updateMask & (POPUP_USER_FIELD_MODE|POPUP_USER_FIELD_HEALTH))
      {
        const QBrush & _foreground = selectBrush(p_user);
        item(_row, TABLE_COLUMN_USERNAME)->setForeground(_foreground);
        item(_row, TABLE_COLUMN_USERMODE)->setForeground(_foreground);
        item(_row, TABLE_COLUMN_LIKE    )->setForeground(_foreground);
        item(_row, TABLE_COLUMN_DONTLIKE)->setForeground(_foreground);
        item(_row, TABLE_COLUMN_POETRY  )->setForeground(_foreground);
        item(_row, TABLE_COLUMN_FUCK    )->setForeground(_foreground);
      }
      if (p_updateMask & POPUP_USER_FIELD_MODE)
      {
        _index = index(_row, TABLE_COLUMN_USERMODE);
        setData(_index, modeToString(p_user->getMode()));
      }
      if (p_updateMask & POPUP_USER_FIELD_NICKNAME) {
        _index = index(_row, TABLE_COLUMN_USERNAME);
        setData(_index, p_user->getNickname().c_str());
      }
      if (p_updateMask & (POPUP_USER_FIELD_AVATAR|POPUP_USER_FIELD_HEALTH))
      {
        if (QFile::exists(p_user->getAvatar().c_str())) {
          _index = index(_row, TABLE_COLUMN_USERNAME);
          QIcon _icon;
          _icon.addFile(QString::fromUtf8(p_user->getAvatar().c_str()), QSize(24,24));
          QIcon::Mode _mode = (p_user->isAlive()? QIcon::Normal : QIcon::Disabled);
          QPixmap _pixmap = _icon.pixmap(QSize(24,24), _mode);
          _icon.addPixmap(_pixmap);
          setData(_index, _icon, Qt::DecorationRole);
        }
      }
    }
  }
}

void PopupUsersTableModel::updateUserStatistics(const PopupUserExt *p_user,
                                                unsigned short p_updateMask)
{
  if (p_user->getID() != getMyID())
  {
    int _row = 0;
    bool _found = false;

    // Find this user in the list
    for (_row = 0; _row < rowCount(); _row++) {
      if (item(_row, 0)->data(PopupGuiCore::POPUP_USER_ID).toUInt() == p_user->getID()) {
        _found = true;
        break;
      }
    }
    // User not found!! Strange!
    if (!_found)
    {
      trace("Ooops! %s:%d", __FUNCTION__, __LINE__);
    }
    else
    {
      // Update statistics
      static const int MAX_NB_ITEMS = 4;
      static const RateItem2ColumnIndex item2Index[MAX_NB_ITEMS] = {
          { POPUP_RATE_LIKE,     TABLE_COLUMN_LIKE },
          { POPUP_RATE_DONTLIKE, TABLE_COLUMN_DONTLIKE },
          { POPUP_RATE_POETRY,   TABLE_COLUMN_POETRY },
          { POPUP_RATE_FUCKYOU,  TABLE_COLUMN_FUCK }
      };

      for (int _i = 0; _i < MAX_NB_ITEMS; _i++) {
        UserRateItem _statItem = item2Index[_i].item;
        int _column = item2Index[_i].index;
        if (p_updateMask & _statItem) {
          QStandardItem *_item = item(_row, _column);
          // Set new stat value
          _item->setData(p_user->statValue(_statItem), Qt::DisplayRole);
          // Record lost!
          if ((!_item->data(POPUP_IS_RECORD).isNull()) &&
              (_item->data(POPUP_IS_RECORD).toBool() == true) &&
              (p_user->stats.isRecordman(_statItem) == false)) {
            _item->setData(false, POPUP_IS_RECORD);
            _item->setData(QIcon(), Qt::DecorationRole);
          }
          // New record
          else if ((_item->data(POPUP_IS_RECORD).toBool() == false) &&
                   (p_user->stats.isRecordman(_statItem) == true)) {
            QIcon _icon;
            _icon.addFile(QString::fromUtf8(":/images/popup_star.png"),
                          QSize(24,24), QIcon::Normal, QIcon::Off);
            _item->setData(_icon, Qt::DecorationRole);
            _item->setData(true, POPUP_IS_RECORD);
          }
        }
      }
    }
  }
}
